using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Joy.Erp.BasicArchives.Core;
using Joy.Erp.BasicArchives.ItemMasters;
using Joy.Erp.BasicArchives.Receipt;
using Joy.Erp.BasicArchives.Staff;
using Joy.Erp.BasicArchives.Storage;
using Joy.Erp.BasicArchives.Suppliers;
using Joy.Erp.Ufida.Core;
using Microsoft.Extensions.Logging;

namespace Joy.Erp.Ufida.Receipt
{
    public class ReceivementSyncAppService : UfidaAppService, IReceivementSyncAppService
    {
        protected IReceivementRepository ReceivementRepository => LazyServiceProvider.LazyGetRequiredService<IReceivementRepository>();
        protected IReceivementTypeRepository ReceivementTypeRepository => LazyServiceProvider.LazyGetRequiredService<IReceivementTypeRepository>();
        protected ISupplierRepository SupplierRepository => LazyServiceProvider.LazyGetRequiredService<ISupplierRepository>();
        protected IOperatorRepository OperatorRepository => LazyServiceProvider.LazyGetRequiredService<IOperatorRepository>();
        protected IItemMasterRepository ItemMasterRepository => LazyServiceProvider.LazyGetRequiredService<IItemMasterRepository>();
        protected IWarehouseRepository WarehouseRepository => LazyServiceProvider.LazyGetRequiredService<IWarehouseRepository>();
        protected IUnitGroupAppService UnitGroupAppService => LazyServiceProvider.LazyGetRequiredService<IUnitGroupAppService>();
        protected IReceivementUfidaAppService ReceivementUfidaAppService => LazyServiceProvider.LazyGetRequiredService<IReceivementUfidaAppService>();

        public async Task<AnalysisDto> AnalyzeAsync(DateTime start, DateTime end)
        {
            var analysisDto = new AnalysisDto();
            analysisDto.Id = typeof(Receivement).FullName;

            // 获取U9数据的ID列表（去重）
            var u9list = await ReceivementUfidaAppService.GetAllAsync(start, end);
            var u9Ids = u9list.Select(x => x.ID.ToString()).Distinct().ToHashSet();
            analysisDto.U9Count = u9Ids.Count;

            // 使用数据库查询优化，只查询需要的字段
            var pmcQuery = await ReceivementRepository.GetQueryableAsync();

            // 获取PMC总数
            analysisDto.Count = await AsyncExecuter.CountAsync(
                pmcQuery.Where(x =>
                    !x.IsDeleted
                    && x.SourceCreatedOn >= start
                    && x.SourceCreatedOn <= end
                    && x.SourceType == SourceConfig.SourceType
                )
            );

            // 获取已同步的SourceKey列表
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x =>
                        !x.IsDeleted
                        && x.SourceCreatedOn >= start
                        && x.SourceCreatedOn <= end
                        && x.SourceType == SourceConfig.SourceType
                    )
                    .Select(x => x.SourceKey)
            );

            // 使用 HashSet 快速计算已同步数量
            analysisDto.AsyncCount = syncedSourceKeys.Count(key => u9Ids.Contains(key));
            analysisDto.UnasyncCount = analysisDto.U9Count - analysisDto.AsyncCount;
            analysisDto.SelfCount = analysisDto.Count - analysisDto.AsyncCount;

            return analysisDto;
        }

        public async Task<List<long>> GetUnasyncIds(DateTime start, DateTime end)
        {
            // 获取U9的所有ID（去重）
            var u9list = await ReceivementUfidaAppService.GetAllAsync(start, end);
            var u9Ids = u9list.Select(x => x.ID).Distinct().ToList();

            // 使用数据库查询，只查询已同步的SourceKey
            var pmcQuery = await ReceivementRepository.GetQueryableAsync();
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x =>
                        !x.IsDeleted
                        && x.SourceCreatedOn >= start
                        && x.SourceCreatedOn <= end
                        && x.SourceType == SourceConfig.SourceType
                    )
                    .Select(x => x.SourceKey)
            );

            // 使用 HashSet 优化查找性能，时间复杂度从 O(n²) 降到 O(n)
            var syncedSourceKeySet = new HashSet<string>(syncedSourceKeys);

            // 找出未同步的ID
            var unasyncIds = u9Ids.Where(id => !syncedSourceKeySet.Contains(id.ToString())).ToList();

            return unasyncIds;
        }

        public async Task<int> CreateByIds‌Async(long[] ids, DateTime start, DateTime end)
        {
            if (ids == null || ids.Length == 0) return 0;

            var successCount = 0;
            var pmcQuery = await ReceivementRepository.GetQueryableAsync();
            var idStrings = ids.Select(id => id.ToString()).ToList();
            var existingSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => idStrings.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );

            var existingSet = new HashSet<string>(existingSourceKeys);
            var needCreateIds = ids.Where(id => !existingSet.Contains(id.ToString())).ToList();
            if (needCreateIds.Count == 0) return ids.Length;

            Logger.LogInformation($"[批量同步-收货单] 开始处理 {needCreateIds.Count} 条");
            var allU9DataDict = new Dictionary<long, List<ReceivementUfidaDto>>();
            foreach (var id in needCreateIds)
            {
                try
                {
                    var items = await ReceivementUfidaAppService.GetLinesAsync(id, start, end);
                    if (items != null && items.Count > 0) allU9DataDict[id] = items;
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-收货单] 获取U9数据失败，Id: {id}");
                }
            }
            if (allU9DataDict.Count == 0) return existingSet.Count;

            var allTypeIds = allU9DataDict.Values.SelectMany(x => x).Select(x => x.DocumentType.ToString()).Distinct().ToList();
            var typeCacheDict = await BatchLoadReceivementTypes(allTypeIds);

            var allSupplierIds = allU9DataDict.Values.SelectMany(x => x).Where(x => x.Supplier != null).Select(x => x.Supplier.ToString()).Distinct().ToList();
            var supplierCacheDict = await BatchLoadSuppliers(allSupplierIds);

            var allOperatorIds = allU9DataDict.Values.SelectMany(x => x).Where(x => x.Operator != null).Select(x => x.Operator.ToString()).Distinct().ToList();
            var operatorCacheDict = await BatchLoadOperators(allOperatorIds);

            var allItemMasterIds = allU9DataDict.Values.SelectMany(x => x).Select(x => x.ItemMasterID.ToString()).Distinct().ToList();
            var itemMasterCacheDict = await BatchLoadItemMasters(allItemMasterIds);

            var allWhIds = allU9DataDict.Values.SelectMany(x => x).Where(x => x.Wh != null).Select(x => x.Wh.ToString()).Distinct().ToList();
            var warehouseCacheDict = await BatchLoadWarehouses(allWhIds);

            var unitGroupCacheDict = await BatchLoadUnitGroupsByItemMasters(itemMasterCacheDict.Values.Select(x => x.UnitGroupId).Distinct().ToList());

            var entities = new List<Receivement>();
            foreach (var kvp in allU9DataDict)
            {
                try
                {
                    var entity = GetEntity(
                        kvp.Value,
                        typeCacheDict,
                        supplierCacheDict,
                        operatorCacheDict,
                        itemMasterCacheDict,
                        unitGroupCacheDict,
                        warehouseCacheDict
                    );
                    if (entity != null) entities.Add(entity);
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-收货单] 创建实体失败，Id: {kvp.Key}");
                }
            }
            if (entities.Count > 0)
            {
                using (var uow = UnitOfWorkManager.Begin(new Volo.Abp.Uow.AbpUnitOfWorkOptions(), requiresNew: true))
                {
                    try
                    {
                        await ReceivementRepository.BulkInsertAsync(entities, autoSave: false);
                        await uow.CompleteAsync();
                        successCount = entities.Count;
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning(ex, $"[批量同步-收货单] 批量插入失败，{ex.Message}");
                    }
                }
            }
            Logger.LogInformation($"[批量同步-收货单] 完成！");
            return successCount + existingSet.Count;
        }

        public async Task<List<long>> GetSyncedIds(DateTime start, DateTime end)
        {
            var pmcQuery = await ReceivementRepository.GetQueryableAsync();
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x =>
                        !x.IsDeleted
                        && x.SourceCreatedOn >= start
                        && x.SourceCreatedOn <= end
                        && x.SourceType == SourceConfig.SourceType
                    )
                    .Select(x => x.SourceKey)
            );
            var result = new List<long>();
            foreach (var key in syncedSourceKeys)
            {
                if (long.TryParse(key, out var id))
                {
                    result.Add(id);
                }
            }
            return result;
        }

        public async Task<int> UpdateByIdsAsync(long[] ids, DateTime start, DateTime end)
        {
            if (ids == null || ids.Length == 0) return 0;

            Logger.LogInformation($"[批量同步-收货单] 开始处理 {ids.Length} 条更新/删除");

            var pmcQuery = await ReceivementRepository.WithDetailsAsync(x => x.Children);
            var idStrings = ids.Select(x => x.ToString()).ToList();
            var existingEntities = await AsyncExecuter.ToListAsync(
                pmcQuery.Where(x =>
                    idStrings.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            if (existingEntities.Count == 0)
            {
                Logger.LogWarning($"[批量同步-收货单] 没有找到需要处理的记录");
                return 0;
            }

            var entityDict = existingEntities.ToDictionary(x => x.SourceKey, x => x);
            var needHandleIds = ids.Where(id => entityDict.ContainsKey(id.ToString())).ToList();
            if (needHandleIds.Count == 0) return 0;

            var allU9DataDict = new Dictionary<long, List<ReceivementUfidaDto>>();
            var entitiesToDelete = new List<Receivement>();
            foreach (var id in needHandleIds)
            {
                if (!entityDict.TryGetValue(id.ToString(), out var entity)) continue;

                try
                {
                    var items = await ReceivementUfidaAppService.GetLinesAsync(id, start, end);
                    if (items != null && items.Count > 0)
                    {
                        allU9DataDict[id] = items;
                    }
                    else
                    {
                        entitiesToDelete.Add(entity);
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-收货单] 获取U9数据失败，Id: {id}");
                }
            }

            var entitiesToUpdate = new List<Receivement>();
            if (allU9DataDict.Count > 0)
            {
                var allTypeIds = allU9DataDict.Values.SelectMany(x => x).Select(x => x.DocumentType.ToString()).Distinct().ToList();
                var typeCacheDict = await BatchLoadReceivementTypes(allTypeIds);

                var allSupplierIds = allU9DataDict.Values.SelectMany(x => x).Where(x => x.Supplier != null).Select(x => x.Supplier.ToString()).Distinct().ToList();
                var supplierCacheDict = await BatchLoadSuppliers(allSupplierIds);

                var allOperatorIds = allU9DataDict.Values.SelectMany(x => x).Where(x => x.Operator != null).Select(x => x.Operator.ToString()).Distinct().ToList();
                var operatorCacheDict = await BatchLoadOperators(allOperatorIds);

                var allItemMasterIds = allU9DataDict.Values.SelectMany(x => x).Select(x => x.ItemMasterID.ToString()).Distinct().ToList();
                var itemMasterCacheDict = await BatchLoadItemMasters(allItemMasterIds);

                var allWhIds = allU9DataDict.Values.SelectMany(x => x).Where(x => x.Wh != null).Select(x => x.Wh.ToString()).Distinct().ToList();
                var warehouseCacheDict = await BatchLoadWarehouses(allWhIds);

                var unitGroupCacheDict = await BatchLoadUnitGroupsByItemMasters(itemMasterCacheDict.Values.Select(x => x.UnitGroupId).Distinct().ToList());

                foreach (var kvp in allU9DataDict)
                {
                    var id = kvp.Key;
                    var u9Items = kvp.Value;
                    try
                    {
                        if (!entityDict.TryGetValue(id.ToString(), out var entity)) continue;

                        entity.Code = u9Items[0].DocNo;
                        entity.BusinessDate = u9Items[0].BusinessDate ?? DateTime.Now.Date;
                        entity.DocumentStatus = ToDocumentStatus(u9Items[0].Status);
                        entity.SourceCreatedOn = u9Items[0].CreatedOn;
                        entity.ArriveDate = u9Items[0].ApprovedOn;
                        entity.Mark = u9Items[0].Memo;

                        if (typeCacheDict.TryGetValue(u9Items[0].DocumentType.ToString(), out var receivementTypeDto))
                        {
                            entity.OrderTypeId = receivementTypeDto.Id;
                        }

                        entity.SupplierId = null;
                        if (u9Items[0].Supplier != null && supplierCacheDict.TryGetValue(u9Items[0].Supplier.ToString(), out var supplierDto))
                        {
                            entity.SupplierId = supplierDto.Id;
                        }

                        entity.OperatorId = null;
                        if (u9Items[0].Operator != null && operatorCacheDict.TryGetValue(u9Items[0].Operator.ToString(), out var operatorDto))
                        {
                            entity.OperatorId = operatorDto.Id;
                        }

                        var existingLinesDict = entity.Children.ToDictionary(x => x.SourceKey);
                        var processedKeys = new HashSet<string>();
                        foreach (var item in u9Items)
                        {
                            if (!itemMasterCacheDict.TryGetValue(item.ItemMasterID.ToString(), out var itemMasterDto)) continue;
                            if (!unitGroupCacheDict.TryGetValue(itemMasterDto.UnitGroupId, out var unitGroupDto)) continue;

                            var auxiliaryUnitDto = unitGroupDto.Children.FirstOrDefault(x => x.SourceType == SourceConfig.SourceType && x.SourceKey == item.PriceUOM.ToString());
                            if (auxiliaryUnitDto == null) continue;

                            Guid? warehouseId = null;
                            if (item.Wh != null && warehouseCacheDict.TryGetValue(item.Wh.ToString(), out var warehouseDto))
                            {
                                warehouseId = warehouseDto.Id;
                            }

                            var sourceKey = item.LineID.ToString();
                            processedKeys.Add(sourceKey);

                            if (existingLinesDict.TryGetValue(sourceKey, out var line))
                            {
                                line.LineNo = item.DocLineNo;
                                line.ItemMasterId = itemMasterDto.Id;
                                line.ItemCode = item.ItemCode;
                                line.ItemName = item.ItemName;
                                line.ItemSpec = itemMasterDto.Spec;
                                line.Quantity = item.Quantity;
                                line.ShipmentQuantity = item.ShipmentQuantity;
                                line.UnitPrice = item.UnitPrice;
                                line.UnitId = auxiliaryUnitDto.Id;
                                line.WarehouseId = warehouseId;
                                line.SourceCreatedOn = item.CreatedOn;
                            }
                            else
                            {
                                var newLine = new ReceivementLine
                                {
                                    SourceType = SourceConfig.SourceType,
                                    SourceKey = sourceKey,
                                    SourceCreatedOn = item.CreatedOn,
                                    LineNo = item.DocLineNo,
                                    ItemMasterId = itemMasterDto.Id,
                                    ItemCode = item.ItemCode,
                                    ItemName = item.ItemName,
                                    ItemSpec = itemMasterDto.Spec,
                                    Quantity = item.Quantity,
                                    ShipmentQuantity = item.ShipmentQuantity,
                                    UnitPrice = item.UnitPrice,
                                    UnitId = auxiliaryUnitDto.Id,
                                    WarehouseId = warehouseId,
                                    DocumentId = entity.Id,
                                    CreationTime = Clock.Now,
                                    CreatorId = CurrentUser.Id,
                                };
                                newLine.SetId(GuidGenerator.Create());
                                entity.Children.Add(newLine);
                            }
                        }

                        var linesToRemove = entity.Children.Where(line => !processedKeys.Contains(line.SourceKey)).ToList();
                        foreach (var line in linesToRemove)
                        {
                            entity.Children.Remove(line);
                        }

                        entitiesToUpdate.Add(entity);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning(ex, $"[批量同步-收货单] 修改实体失败，Id: {id}");
                    }
                }
            }

            if (entitiesToUpdate.Count == 0 && entitiesToDelete.Count == 0)
            {
                Logger.LogInformation($"[批量同步-收货单] 无需更新或删除记录");
                return 0;
            }

            var updateCount = 0;
            var deleteCount = 0;
            using (var uow = UnitOfWorkManager.Begin(new Volo.Abp.Uow.AbpUnitOfWorkOptions(), requiresNew: true))
            {
                try
                {
                    if (entitiesToUpdate.Count > 0)
                    {
                        await ReceivementRepository.BulkUpdateAsync(entitiesToUpdate, autoSave: false);
                        updateCount = entitiesToUpdate.Count;
                    }

                    if (entitiesToDelete.Count > 0)
                    {
                        await ReceivementRepository.BulkDeleteAsync(entitiesToDelete, autoSave: false);
                        deleteCount = entitiesToDelete.Count;
                    }

                    await uow.CompleteAsync();
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-收货单] 批量更新/删除失败，{ex.Message}");
                }
            }

            Logger.LogInformation($"[批量同步-收货单] 完成！成功更新 {updateCount} 条，删除 {deleteCount} 条");
            return updateCount + deleteCount;
        }

        public DocumentStatus ToDocumentStatus(int status)
        {
            if (status == 0)
            {
                return DocumentStatus.Open;
            }
            else if (status == 1 || status == 2 || status == 3)
            {
                return DocumentStatus.Waiting;
            }
            else if (status == 4)
            {
                return DocumentStatus.Approved;
            }
            else if (status == 5)
            {
                return DocumentStatus.Closed;
            }

            return DocumentStatus.Open;
        }

        private async Task<Dictionary<string, ReceivementTypeDto>> BatchLoadReceivementTypes(List<string> sourceKeys)
        {
            if (sourceKeys == null || sourceKeys.Count == 0) return new Dictionary<string, ReceivementTypeDto>();

            var query = await ReceivementTypeRepository.GetQueryableAsync();
            var items = await AsyncExecuter.ToListAsync(
                query.Where(x =>
                    sourceKeys.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            return items.ToDictionary(
                x => x.SourceKey,
                x => ObjectMapper.Map<ReceivementType, ReceivementTypeDto>(x)
            );
        }

        private async Task<Dictionary<string, SupplierDto>> BatchLoadSuppliers(List<string> sourceKeys)
        {
            if (sourceKeys == null || sourceKeys.Count == 0) return new Dictionary<string, SupplierDto>();

            var query = await SupplierRepository.GetQueryableAsync();
            var items = await AsyncExecuter.ToListAsync(
                query.Where(x =>
                    sourceKeys.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            return items.ToDictionary(
                x => x.SourceKey,
                x => ObjectMapper.Map<Supplier, SupplierDto>(x)
            );
        }

        private async Task<Dictionary<string, OperatorDto>> BatchLoadOperators(List<string> sourceKeys)
        {
            if (sourceKeys == null || sourceKeys.Count == 0) return new Dictionary<string, OperatorDto>();

            var query = await OperatorRepository.GetQueryableAsync();
            var items = await AsyncExecuter.ToListAsync(
                query.Where(x =>
                    sourceKeys.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            return items.ToDictionary(
                x => x.SourceKey,
                x => ObjectMapper.Map<Operator, OperatorDto>(x)
            );
        }

        private async Task<Dictionary<string, ItemMasterDto>> BatchLoadItemMasters(List<string> sourceKeys)
        {
            if (sourceKeys == null || sourceKeys.Count == 0) return new Dictionary<string, ItemMasterDto>();

            var query = await ItemMasterRepository.GetQueryableAsync();
            var items = await AsyncExecuter.ToListAsync(
                query.Where(x =>
                    sourceKeys.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            return items.ToDictionary(
                x => x.SourceKey,
                x => ObjectMapper.Map<ItemMaster, ItemMasterDto>(x)
            );
        }

        private async Task<Dictionary<Guid, UnitGroupDto>> BatchLoadUnitGroupsByItemMasters(List<Guid> unitGroupIds)
        {
            if (unitGroupIds == null || unitGroupIds.Count == 0)
                return new Dictionary<Guid, UnitGroupDto>();
            var result = new Dictionary<Guid, UnitGroupDto>();
            foreach (var unitGroupId in unitGroupIds.Distinct())
            {
                try
                {
                    result[unitGroupId] = await UnitGroupAppService.GetAsync(unitGroupId);
                }
                catch { }
            }
            return result;
        }

        private async Task<Dictionary<string, WarehouseDto>> BatchLoadWarehouses(List<string> sourceKeys)
        {
            if (sourceKeys == null || sourceKeys.Count == 0)
                return new Dictionary<string, WarehouseDto>();
            var query = await WarehouseRepository.GetQueryableAsync();
            var items = await AsyncExecuter.ToListAsync(
                query.Where(x =>
                    sourceKeys.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            return items.ToDictionary(
                x => x.SourceKey,
                x => ObjectMapper.Map<Warehouse, WarehouseDto>(x)
            );
        }

        private Receivement GetEntity(
            List<ReceivementUfidaDto> items,
            Dictionary<string, ReceivementTypeDto> typeCacheDict,
            Dictionary<string, SupplierDto> supplierCacheDict,
            Dictionary<string, OperatorDto> operatorCacheDict,
            Dictionary<string, ItemMasterDto> itemMasterCacheDict,
            Dictionary<Guid, UnitGroupDto> unitGroupCacheDict,
            Dictionary<string, WarehouseDto> warehouseCacheDict
        )
        {
            if (!typeCacheDict.TryGetValue(items[0].DocumentType.ToString(), out var typeDto)) return null;

            Guid? supplierId = null;
            if (items[0].Supplier != null && supplierCacheDict.TryGetValue(items[0].Supplier.ToString(), out var supplierDto))
            {
                supplierId = supplierDto.Id;
            }

            Guid? operatorId = null;
            if (items[0].Operator != null && operatorCacheDict.TryGetValue(items[0].Operator.ToString(), out var operatorDto))
            {
                operatorId = operatorDto.Id;
            }

            var entityId = GuidGenerator.Create();
            var entity = new Receivement
            {
                SourceType = SourceConfig.SourceType,
                SourceKey = items[0].ID.ToString(),
                SourceCreatedOn = items[0].CreatedOn,
                Code = items[0].DocNo,
                BusinessDate = items[0].BusinessDate ?? DateTime.Now.Date,
                DocumentStatus = ToDocumentStatus(items[0].Status),
                OrderTypeId = typeDto.Id,
                SupplierId = supplierId,
                OperatorId = operatorId,
                ArriveDate = items[0].ApprovedOn,
                Mark = items[0].Memo,
                CreationTime = Clock.Now,
                CreatorId = CurrentUser.Id,
                TenantId = CurrentTenant.Id,
            };
            entity.SetId(entityId);
            foreach (var item in items)
            {
                if (!itemMasterCacheDict.TryGetValue(item.ItemMasterID.ToString(), out var itemMasterDto)) continue;
                if (!unitGroupCacheDict.TryGetValue(itemMasterDto.UnitGroupId, out var unitGroupDto)) continue;

                var auxiliaryUnitDto = unitGroupDto.Children.FirstOrDefault(x => x.SourceType == SourceConfig.SourceType && x.SourceKey == item.PriceUOM.ToString());
                if (auxiliaryUnitDto == null) continue;

                Guid? warehouseId = null;
                if (item.Wh != null && warehouseCacheDict.TryGetValue(item.Wh.ToString(), out var warehouseDto))
                {
                    warehouseId = warehouseDto.Id;
                }

                var line = new ReceivementLine
                {
                    SourceType = SourceConfig.SourceType,
                    SourceKey = item.LineID.ToString(),
                    SourceCreatedOn = item.CreatedOn,
                    LineNo = item.DocLineNo,
                    ItemMasterId = itemMasterDto.Id,
                    ItemCode = item.ItemCode,
                    ItemName = item.ItemName,
                    ItemSpec = itemMasterDto.Spec,
                    Quantity = item.Quantity,
                    ShipmentQuantity = item.ShipmentQuantity,
                    UnitPrice = item.UnitPrice,
                    UnitId = auxiliaryUnitDto.Id,
                    WarehouseId = warehouseId,
                    DocumentId = entityId,
                    CreationTime = Clock.Now,
                    CreatorId = CurrentUser.Id,
                };
                line.SetId(GuidGenerator.Create());
                entity.Children.Add(line);
            }
            return entity;
        }
    }
}
